/****************************************************************************/
/*                                                                          */
/*  The FreeType project -- a free and portable quality font engine         */
/*                                                                          */
/*  Copyright 1996-1998 by                                                  */
/*  D. Turner, R.Wilhelm, and W. Lemberg                                    */
/*                                                                          */
/*  ftlint: a simple font tester. This program tries to load all the        */
/*          glyphs of a given font.                                         */
/*                                                                          */
/*  NOTE:  This is just a test program that is used to show off and         */
/*         debug the current engine.                                        */
/*                                                                          */
/****************************************************************************/

#include <ft2build.h>
#include FT_FREETYPE_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define gettext( x )  ( x )

FT_Error error;

FT_Library library;

FT_Face face;

FT_Size size;

FT_GlyphSlot slot;

unsigned int num_glyphs;

int ptsize;

int Fail;

int Num;

int renderok = 0;


static void Usage(char *name)
{
    printf("ftlint: simple font tester -- part of the FreeType project\n");
    printf("----------------------------------------------------------\n");
    printf("\n");
    printf("Usage: %s size fontfilename outputfilename\n", name);
    printf("\n");

    exit(1);
}


static void Panic(const char *message)
{
    fprintf(stderr, "%s\n  error code = 0x%04x\n", message, error);
    exit(1);
}


#define MAX_CI 2000
struct s_newfont_ci {
    unsigned short start_code;
    unsigned char count;
    unsigned char width;
    unsigned int offset;
} ci[MAX_CI];;
int total_ci;


int main(int argc, char **argv)
{
    int i, file_index;

    unsigned int id;

    char *execname;

    execname = argv[0];

    if (argc != 4)
        Usage(execname);

    if (sscanf(argv[1], "%d", &ptsize) != 1)
        Usage(execname);

    error = FT_Init_FreeType(&library);
    if (error)
        Panic("Could not create library object");

    /* try to open the file with no extra extension first */
    error = FT_New_Face(library, argv[2], 0, &face);
    if (!error) {
        printf("%s: ", argv[2]);
    } else {
        printf("unknow file format\n");
        return -1;
    }

    num_glyphs = face->num_glyphs;

    error = FT_Set_Char_Size(face, (ptsize) << 6, (ptsize) << 6, 72, 72);
    if (error)
        Panic("Could not set character size");

    total_ci = 0;
    unsigned short cur_ci_start = 0;

    unsigned short cur_ci_end = 0;

    int last_width = 0;

    for (i = 0x1; i < 0xffa0; i++) {
        if ((id = FT_Get_Char_Index(face, i)) > 0) {

            error = FT_Load_Glyph(face, id, FT_LOAD_DEFAULT);
            if (error == 0) {
                error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);
                if (error == 0) {
//                                      printf("%d\n", face->glyph->bitmap.width);
                }
            }

            if (cur_ci_start == 0) {
                cur_ci_start = i;
                cur_ci_end = i;
                last_width = face->glyph->bitmap.width + face->glyph->bitmap_left;
            } else {
                if (i - cur_ci_start >= 255 || last_width != face->glyph->bitmap.width + face->glyph->bitmap_left) {

                    ci[total_ci].start_code = cur_ci_start;
                    ci[total_ci].width = last_width;
                    ci[total_ci].count = cur_ci_end - cur_ci_start + 1;

                    total_ci++;
                    if (total_ci >= MAX_CI) {
                        printf("please increase CI\n");
                        exit(0);
                    }
                    cur_ci_start = i;
                    cur_ci_end = i;
                    last_width = face->glyph->bitmap.width + face->glyph->bitmap_left;
                } else {
                    cur_ci_end = i;
                }
            }
        }
    }

    ci[total_ci].start_code = cur_ci_start;
    ci[total_ci].width = last_width;
    ci[total_ci].count = cur_ci_end - cur_ci_start + 1;
    total_ci++;

    printf("ci: %d.\n", total_ci);

    int offset = 16 + total_ci * 8;

    int off2 = 0;

    int j;

    j = 0;
    for (i = 0; i < total_ci; i++) {
        ci[i].offset = offset + off2;
        off2 += ((ci[i].width + 7) >> 3) * ptsize * ci[i].count;
        j += ci[i].count;
    }
    printf("filesize should be :%d, %d\n", offset + off2, j);

    FILE *fp;

    char buf[256];

    fp = fopen(argv[3], "w");
    if (fp == NULL) {
        printf("cannot create output %s\n", argv[3]);
        return;
    }

    fwrite("HE01", 1, 4, fp);
    buf[0] = ptsize;
    buf[1] = 0;
    buf[2] = 0;
    buf[3] = 0;
    fwrite(buf, 1, 4, fp);

    buf[0] = total_ci & 0xff;
    buf[1] = (total_ci >> 8) & 0xff;
    buf[2] = (total_ci >> 16) & 0xff;
    buf[3] = (total_ci >> 24) & 0xff;
    fwrite(buf, 1, 4, fp);

    buf[0] = 0;
    buf[1] = 0;
    buf[2] = 0;
    buf[3] = 0;
    fwrite(buf, 1, 4, fp);

    for (i = 0; i < total_ci; i++) {
        fwrite(&ci[i], 1, 8, fp);
    }

    int k, kk;

    int ko;

    unsigned char *cbuf;

    char *obuf;

    for (i = 0; i < total_ci; i++) {
        for (j = 0; j < ci[i].count; j++) {

            memset(buf, 0, 64);

            if ((id = FT_Get_Char_Index(face, ci[i].start_code + j)) > 0) {
                error = FT_Load_Glyph(face, id, FT_LOAD_DEFAULT);
                if (error == 0) {
                    error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);
                    if (error == 0) {

//                                              printf("%d, %d\n", face->glyph->bitmap.rows, face->glyph->bitmap.pitch);

                        int row_start;

                        k = ptsize - (2 + face->glyph->bitmap_top);
                        if (k < 0)
                            k = 0;
                        row_start = k;

                        cbuf = face->glyph->bitmap.buffer;
                        obuf = buf;
                        //align bottom
                        obuf += k * ((ci[i].width + 7) >> 3);
                        for (; k < ptsize && k < row_start + face->glyph->bitmap.rows; k++, cbuf += face->glyph->bitmap.pitch, obuf += (ci[i].width + 7) >> 3) {
                            ko = face->glyph->bitmap_left;
                            for (kk = 0; kk < face->glyph->bitmap.width; kk++, ko++) {
                                if (cbuf[kk / 8] & (1 << (7 - (kk & 7)))) {
                                    obuf[ko / 8] |= (1 << ((ko & 7)));
                                }
                            }
                        }
                    }
                }
            }

            fwrite(buf, 1, ((ci[i].width + 7) >> 3) * ptsize, fp);

        }

    }

    fclose(fp);

    FT_Done_Face(face);

    FT_Done_FreeType(library);
    exit(0);                    /* for safety reasons */

    return 0;                   /* never reached */
}


/* End */
